iT邦幫忙

2024 iThome 鐵人賽

DAY 28
0
Software Development

Laravel 隨筆學習札記系列 第 28

Day28 - Eloquent 資源的魔法:讓 API Resources 輸出更簡單

  • 分享至 

  • xImage
  •  

Laravel API Resource 可以怎麼幫我們輕鬆管理 API 回應,讓資料變得更易讀、更有吸引力呢?

讓我們一起來探究吧~


Introduction

哈🤗一定要先看看官方網站怎麼說!

When building an API, you may need a transformation layer that sits between your Eloquent models and the JSON responses that are actually returned to your application's users. For example, you may wish to display certain attributes for a subset of users and not others, or you may wish to always include certain relationships in the JSON representation of your models. Eloquent's resource classes allow you to expressively and easily transform your models and model collections into JSON.>

Of course, you may always convert Eloquent models or collections to JSON using their toJson methods; however, Eloquent resources provide more granular and robust control over the JSON serialization of your models and their relationships.

大概的意思字講說

在建立 API 時,通常需要一個轉換層來處理 Eloquent 模型和實際返回給使用者的 JSON 數據。

我們可以想像,如果想要對某些使用者顯示特定的資料,而對其他使用者不顯示,又或者希望在 JSON 裡包含某些關聯的資料。Laravel 的 Resource ****類別可以讓我們輕鬆地將這些模型和資料轉換成 JSON 格式。

雖然可以使用 toJson 方法直接將模型轉換成 JSON,但使用 Resource 類別可以讓我們更靈活地控制哪些資料在 JSON 中出現,這樣就能更精確地定義資料的結構和關聯。


Generating Resources

individual models

單個Resource用於表示單一模型的資料結構,適合返回單個實體(如單個使用者的詳細資料),使用 Artisan 命令 make:resource Resource 通常是放在應用程式的app/Http/Resources 目錄中

php artisan make:resource UserResource

Resource Collections

集合 Resource 用於表示多個模型的資料結構,適合返回一組實體(如所有用使用者的列表),集合 Resource 會繼承 Illuminate\Http\Resources\Json\ResourceCollection 類別

// 方式一:創建Resource時使用 --collection

php artisan make:resource User --collection
 
// 方式二:在Resource名稱中包含單詞 Collection 將向 Laravel 表明它應該創建一個集合Resource

php artisan make:resource UserCollection

Concept Overview

individual models

Laravel 是怎麼使用 Resource 的?Resource 主要是用來把單個模型轉換成 JSON 格式。

以下面 UserResource 類別為例,每個Resource類別都有一個 toArray 方法,這個方法會把模型的屬性轉換成 JSON 格式,然後作為路由或控制器的回應返回。我們在這裡可以看到,能直接用 $this 指向模型的屬性,因為 Resource 類別會自動把這些請求轉發給底層的模型。

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

當 Resource 定義好之後,我們返回 UserResource

use App\Http\Resources\UserResource;
use App\Models\User;

Route::get('/user/{id}', function (string $id) {
    return new UserResource(User::findOrFail($id));
});

Resource Collections

  • 創建 Resource Collections:使用 Resource ****類別的 collection 方法返回Resource。
use App\Http\Resources\UserResource;
use App\Models\User;

Route::get('/users', function () {
    return UserResource::collection(User::all());
});
  • 生成 Resource Collections 回應:使用 php artisan make:resource 指令創建一個專門的Resource來表示這個集合:
php artisan make:resource UserCollection
  • 定義 Resource Collections 的內容:在Resource集合類中定義回應內容。
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;

class UserCollection extends ResourceCollection
{
    /**
     * 將Resource集合轉換為陣列。
     *
     * @return array<int|string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'data' => $this->collection,
            'links' => [
                'self' => 'link-value',
            ],
        ];
    }
}
  • 返回自定義的 Resource 集合:最後,從路由返回自定義的 UserCollection
use App\Http\Resources\UserCollection;
use App\Models\User;

Route::get('/users', function () {
    return new UserCollection(User::all());
});

Preserving Collection Keys

如果我們希望保留 key(例如使用者的 ID),我們可以使用 preserveKeys 屬性。因為,當我們從路由返回Resource集合時,Laravel 會自動將這些 key 重設為連續的數字,像是 0、1、2 這樣的順序

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    // 將 preserveKeys 設定為 true 時,返回的集合會保留原始的 key
    public $preserveKeys = true;
}

接下來寫入 ->keyBy->id 就可以使用了

use App\Http\Resources\UserResource;
use App\Models\User;

Route::get('/users', function () {
    return UserResource::collection(User::all()->keyBy->id);
});

Customizing the Underlying Resource Class

我們可以透過修改 $collects 這個屬性,來覆蓋Resource集合中 $this->collection 的預設行為。這樣一來,$this->collection 就不再自動把每個項目連接到預設的單一 Resource 類別,而是使用我們指定的類別。

<?php

namespace App\\Http\\Resources;

use Illuminate\\Http\\Resources\\Json\\ResourceCollection;

class UserCollection extends ResourceCollection
{
		// 修改 $collects 這個屬性
    public $collects = Member::class;
}

今天做了初步的了解,明天再繼續研究還有什麼超厲害的功能!


參考資料:

  1. Laravel Advanced - Eloquent Api Resource - Complete Explanation
  2. Laravl官方網站 - Eloquent: API Resources

踏著身心靈的塔羅腳步,轉向技術與邏輯的工程師之路,就藉由塔羅日抽來紀錄今日的學習與生活吧!

寶劍皇后逆位:鐵人賽逐漸來到尾聲,每天的衝刺累累抖~ 但因為在做喜歡的事情,就可以在頭暈的日子還是很開薰🤭

“Being free and uninhibited is beautiful. Trying something new is invigorating. Don't live a boring life if you can add a little silly into it every once in a while.”

無拘無束且不受壓抑是件很美的事,而嘗試新事物可以振奮人心,別讓人生過得太無趣,有時要加一點傻勁和玩心🩷

— Lily Collins


上一篇
Day27 - Gates 與 Policies:Laravel 中的權限管理解決方案
下一篇
Day29 - Eloquent 資源的魔法:Laravel API Resources 的關聯資料管理秘訣!
系列文
Laravel 隨筆學習札記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言